/* ================================================================================
//	Crypteviant!
//	Providing tough encrypted P2P Chat
//	Copyright (C) 2010  Martin Pfeifer, Tobias Rausch
//
//	This program is free software: you can redistribute it and/or modify
//	it under the terms of the GNU General Public License as published by
//	the Free Software Foundation, either version 3 of the License, or
//	(at your option) any later version.
//
//	This program is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU General Public License for more details.
//
//	You should have received a copy of the GNU General Public License
//	along with this program.  If not, see <http://www.gnu.org/licenses/>.
// ============================================================================== */

#ifndef SHA512_HPP
#define SHA512_HPP

#include "abstracthash.hpp"
#include "sha.h"
#include "hex.h"

namespace Hash {

    /**
     * @brief Perform hash operations based on the SHA512 standard
     * @details This class is used as a wrapper for the SHA512 implementation of Crypto++.\n
     * It is there to provide a standard interface to hash operations and to be easily replaced
     * by new hash methods or own implementations.
     *
     * @class Sha512 sha512.hpp "sha512.hpp"
    */
    class Sha512 : public AbstractHash
    {
    public:
        /**
         * @brief Default Constructor
         * @details Initializes the initial buffer with null.
         *
         * @fn Sha512()
        */
        Sha512();

        /**
         * @brief Destructor
         * @details Cleanup and destroy object
         *
         * @fn ~Sha512()
        */
        ~Sha512();

        /**
         * @brief Add data to the buffer
         * @details Add the given data to the buffer. The data may not be hashed directly, it will be stored
         * in the buffer until a call to @ref hash() which performs the hash operation of the whole buffer.
         *
         * @fn update(const QString)
         * @param data
        */
        void update(const QString data);

        /**
         * @brief Hash the internal buffer
         * @details The hash value of the internal buffer will be calculated and returned as a hexadecimal
         * encoded string. You can add data to the buffer with calls to the @ref update(QString) function.\n
         * \b Note: For better security reasons the data will be hashed twice.
         *
         * @fn hash()
         * @return QString
        */
        QString hash();

        /**
         * @brief Perform the hash directly on the data
         * @details The hash value of the given data will be calculated and returned as a hexadecimal
         * string. The internal buffer will not be used and therefore cannot influence the hash value.
         *
         * @fn generateHash(QString)
         * @param data
         * @return QString
        */
        QString generateHash(QString &data) const;

        /**
         * @brief Reset internal data buffers
         * @details Reset the internal buffer.
         *
         * @fn reset()
        */
        void reset();

        /**
         * @brief Return the optimal block size
         * @details This represents the optimal block size for adding data to the hash store.
         *
         * @fn optimalBlockSize()
         * @return int
        */
        int optimalBlockSize() const;

    private:
        /**
         * @brief Encode a given array to a hexadecimal String
         * @details The given byte array will be encoded to hexadecimal String values and returned as a QString.
         *
         * @fn encodeHex
         * @param input
         * @param length
         * @return byte*
        */
        byte *encodeHex(byte *input, int length = 0) const;

        /**
         * @var m_hash
         * @brief Represents the hash as SHA512 which is hashed on-the-fly.\n
         * only one iteration until @ref EntropyPoolData::getData() has been called
        */
        CryptoPP::SHA512 m_hash;
    };

} // End of Namespace Hash

#endif // SHA512_HPP
